<template>
  <div :class="animate" :style="{ height: height, width: width }" :id="chartOption.bindingDiv" ref="chartDiv">
    
  <div :style="textStyle" @click="handleClick">

      
      {{chartOption.textStyle.content}}

    </div>

   <div v-if="flag" :id="chartOption.bindingDiv+'-wrapper'" style="z-index:99999;position:fixed;top:0;right:0;bottom:0;left:0;overflow:auto;margin:0;background:#ffffff42">

      <div :id="chartOption.bindingDiv+'-dialog'" style="z-index:99999;position: relative;margin: 0 auto 50px;background-color: #fff;margin-top: 15vh;width: 30%;height:400px">

        <div :id="chartOption.bindingDiv+'-close'" style="z-index:99999;float:right;margin-right:20px;margin-top:10px;cursor:default" @click="handleClose">关闭 <i class="el-icon-close" style="font-size:16px"></i></div>

      </div>
    </div>


    
    
  </div>
</template>

<script>

import '../../animate/animate.css'
import { remoteTabApi,chartApiBar } from "@/api/tool/datav/chartApi";
import {parseQueryString, fIsUrL} from '../../util/urlUtil'
import { websocketCommand } from "../../util/websocket.js";
import VueEvent from '@/views/tool/datav/VueEvent'
import { forEach } from 'jszip';
const animationDuration = 6000;

export default {
  props: {
    className: {
      type: String,
      default: "chart",
    },
    width: {
      type: String,
      default: "100%",
    },
    height: {
      type: String,
      default: "100%",
    },
    chartOption: {
      type: Object,
    },
    pageState:{
      type: String,
      default: "edit",
    },
    drawingList: {
      type: Array
    }
  },
  data() {
    return {
      // dataOption: this.chartOption,
      timer: "",
      wsObj: null,
      wsFlag: false,
      wsTimer: "",
      wsValue: null,
      controlWsObj: null,
      controlWsFlag: false,
      controlWsTimer: "",
      animate: this.className,
      flag: false,
      wapperId: this.chartOption.bindingDiv+"-wapper",
      closeId:this.chartOption.bindingDiv+"-close",
      staticValue:""
    };
  },
  watch: {
    width() {
      
    },
    height() {
      
    },
    chartOption: {
      deep: true,
      handler(newVal) {
        this.setOptions(JSON.parse(JSON.stringify(newVal)));
      }
    },
    "chartOption.timeout": {
      handler() {
        this.chart = null;
        this.initChart();
      }
    },
    "chartOption.dataSourceType": {
      handler(value) {
        //切换数据源重新连接
        if (value !== "websocket") {
          this.wsFlag = false;
          //每次切换数据源恢复原来动画
          this.animate = this.className;
        }
        if (value !== "url") {
          clearTimeout(this.timer);
        } 
      }
    },
    "chartOption.interfaceKey": {
      handler(newValue, oldValue) {
        //初始化不创建连接，改变接口地址重新创建
        if (oldValue !== undefined && oldValue != "") {
          this.wsValue = null;
          this.closeWs();
          this.createWs();
          this.animate = this.className;
        }
      }
    },
    wsFlag: {
      handler(value) {
        if (!value) {
          this.wsValue = null;
          this.closeWs();
        }
      }
    },
    className: {
      handler(value) {
        this.animate = value;
      }
    },
    "chartOption.isControl": {
      handler(value) {
        //切换数据源重新连接
        if (!value) {
          this.controlWsFlag = false;
          //每次切换数据源恢复原来动画
          this.animate = this.className;
        }
      }
    },
    "chartOption.controlKey": {
      handler(newValue, oldValue) {
        //删除键值断开连接
        if((oldValue !== undefined && oldValue != "" )&& (newValue == undefined || newValue == "")){
          this.controlWsFlag = false;
         
        }
        this.animate = this.className;
      }
    },
     controlWsFlag: {
      handler(value) {
        if (!value) {
          this.controlCloseWs();
        }
      }
    },
    flag: {
      handler(value) {
        if (value) {
           this.$nextTick(() => {
            this.initChart();
          });
        }
      }
    },
  },
  mounted() {
    this.$nextTick(() => {
      this.initChart();
        //设置弹窗父组件置顶
       if(this.pageState != 'edit'){

        document.getElementById(this.chartOption.bindingDiv).parentNode.style.zIndex = "9999";
        
        this.chartOption.events.forEach(element => {

          if(element.chartHide){

             document.getElementById(element.chart).style.visibility = 'hidden'

          }
          
        });

      }

    });
  },
  
  beforeDestroy() {
    
    clearTimeout(this.timer);
    if (this.wsFlag) {
      this.closeWs();
    }
    if (this.controlWsFlag) {
      this.controlCloseWs();
    }
  },
  computed:{
    textStyle(){
      let style = {
        width:"100%",
        height:"100%",
        fontSize: this.chartOption.textStyle.fontSize + "px",
        fontFamily: this.chartOption.textStyle.fontFamily,
        fontWeight: this.chartOption.textStyle.fontWeight,
        color: this.chartOption.textStyle.fontColor,
        letterSpacing:this.chartOption.textStyle.letterSpacing + "px",
        lineHeight:this.chartOption.textStyle.lineHeight + "px",
        textAlign: this.chartOption.textStyle.textAlign,
        cursor:"default"
      };

      if(this.chartOption.background.type == 'color'){
        style.backgroundColor = this.chartOption.background.backgroundColor;
      }else{
        style.backgroundImage = `url(${this.chartOption.background.backgroundImg}) `;
        style.backgroundRepeat = 'no-repeat';
        style.backgroundSize = '100% 100%';
      }

        

      return style;
    }
  },
  methods: {
    initChart() {
      
      //判断是否开启定时器，当是访问url接口时候并且timeout不为0时候开启定时器
      if (this.timer != "") {
        clearTimeout(this.timer);
      }
      if (
        (this.chartOption.dataSourceType == 'url' || this.chartOption.dataSourceType == 'database') &&
        this.chartOption.timeout > 0
      ) {
        let timerTask = () => {
          this.setOptions(JSON.parse(JSON.stringify(this.chartOption)));
          this.timer = setTimeout(() => {
           
            timerTask();
          }, this.chartOption.timeout);
        };

        timerTask();
      }else{
         this.setOptions(JSON.parse(JSON.stringify(this.chartOption)));
      }
      
    },
    setOptions: async function(dataOption) {
      //初始化数据
      if (dataOption.dataSourceType == "url" || dataOption.isStaticData == false) {
        let paramJson = parseQueryString(dataOption.requestParameters);
        let interfaceURL = dataOption.interfaceURL;
        
        dataOption.staticDataValue = await chartApiBar(
          dataOption.requestMethod,
          interfaceURL,
          paramJson,
          dataOption.token
        );


      } else if (dataOption.dataSourceType == "database") {
      } else if (dataOption.dataSourceType == "websocket") {
        if (
          dataOption.interfaceKey != undefined &&
          dataOption.interfaceKey != ""
        ) {
          if (!this.wsFlag) {
            this.wsFlag = true;
            this.wsValue = null;
            this.createWs();
          }
          if (this.wsValue != null) {
            dataOption.staticDataValue = this.wsValue;
          }
        }
      } 

      this.staticValue = dataOption.staticDataValue;

      if(dataOption.isControl == true){
        if (dataOption.controlKey != undefined &&dataOption.controlKey != "") {
          if (!this.controlWsFlag) {
            this.controlWsFlag = true;
            this.controlCreateWs();
          }else{
            this.controlCloseWs();
            this.controlCreateWs();
          }
        }
      }


      dataOption.events.forEach(element => {
        
        if(element.type == 'change'){
          this.runCode(element)
        }
      });

      if(dataOption.customData != undefined && dataOption.customData != ""){

        //数据处理
       dataOption.staticDataValue = (
         
           //里面为要处理的代码块
          eval(dataOption.customData) 
         
         )(
           dataOption.staticDataValue,
           this.$refs.chartDiv
         );
       
      }
    },
    runCode(element){
      if(this.pageState != 'edit'){

        if(element.condition != undefined && element.condition != ""){
              //执行条件代码
              let state = (
              
                //里面为要处理的代码块
                eval(element.condition) 
              
              )(
                this.staticValue,

              );

              //如果条件为真
              if(typeof state == "boolean" && state == true){
                if(element.chartType == 'popup'){
                  //当前选中弹窗置顶，其余弹窗恢复原有zindex
                  this.drawingList.forEach(element => {
                    if(element.chartType == 'interact'){
                      document.getElementById(element.chartOption.bindingDiv).parentNode.style.zIndex = "9999";
                    }
                  });

                    document.getElementById(this.chartOption.bindingDiv).parentNode.style.zIndex = "99999";

                  this.flag = true;
                  
                  //如果开启了远程控制
                  if(this.chartOption.isRemote === true && this.chartOption.remoteKey !== undefined && this.chartOption.remoteKey !== ''){
                    
                    let remoteData = {};
                    
                    remoteData.result = true;
                    remoteData.key = this.chartOption.remoteKey;

                    remoteTabApi(remoteData);

                  }

                }else{
                  //如果绑定组件不为空并且动作不为空
                  if(element.chart != null && element.act != ''){

                    //组件数据变化
                    if(element.act == 'change'){

                      VueEvent.$emit('interactChange',element.chart,element.customConfig) 

                    }
                    //组件显隐
                    else{
                      VueEvent.$emit('interactShow',element.chart,element.act)
                    }
                    
                  }
                
                }

              }
                
        }
        
        
      }
    },
    handleClick(){
      if(this.pageState != 'edit'){

        this.chartOption.events.forEach(element => {
          if(element.type == 'click'){
            if(element.chartType == 'popup'){
              
              //当前选中弹窗置顶，其余弹窗恢复原有zindex
              
              this.drawingList.forEach(element => {
                if(element.chartType == 'interact'){
                  document.getElementById(element.chartOption.bindingDiv).parentNode.style.zIndex = "9999";
                }
                 
              });

               document.getElementById(this.chartOption.bindingDiv).parentNode.style.zIndex = "99999";

              this.flag = true;
              //如果开启了远程控制
              if(this.chartOption.isRemote === true && this.chartOption.remoteKey !== undefined && this.chartOption.remoteKey !== ''){
                
                let remoteData = {};
                
                remoteData.result = true;
                remoteData.key = this.chartOption.remoteKey;

                remoteTabApi(remoteData);

              }

            }else{
              //如果绑定组件不为空并且动作不为空
              if(element.chart != null && element.act != ''){

                let remoteData = {};

                //组件数据变化
                if(element.act == 'change'){
                  remoteData.result = {chart:element.chart,act:element.customConfig};
                 

                  VueEvent.$emit('interactChange',element.chart,element.customConfig) 

                }
                //组件显隐
                else{
                  remoteData.result = {chart:element.chart,act:element.act};
                  VueEvent.$emit('interactShow',element.chart,element.act)
                }

                 //如果开启了远程控制
                if(this.chartOption.isRemote === true && this.chartOption.remoteKey !== undefined && this.chartOption.remoteKey !== ''){
                               
                  remoteData.key = this.chartOption.remoteKey;

                  remoteTabApi(remoteData);

                }
                
              }
            }
          }
          
        });
      }
    },
    handleClose(){
      this.flag = false;
      //如果开启了远程控制
      if(this.chartOption.isRemote === true && this.chartOption.remoteKey !== undefined && this.chartOption.remoteKey !== ''){
        
        let remoteData = {};
        
        remoteData.result = false;
        remoteData.key = this.chartOption.remoteKey;

        remoteTabApi(remoteData);

      }
    },
    //  ws连接成功，后台返回的ws数据
    controlReceiveMsg(e) {
      if (e.action == "chat") {
        // console.log('服务端推送',e);
        
        if(this.pageState != 'edit'){
          let selectValue = JSON.parse(e.result);

           //弹窗
          if(typeof selectValue == 'boolean'){

            if(selectValue){
            this.flag = true;
            }else{
              this.flag = false;
            }

          }else{
            //组件数据变化
            if(typeof selectValue.act != 'string'){
              VueEvent.$emit('interactChange',selectValue.chart,selectValue.act) 
            }
            //组件显隐
            else{
              VueEvent.$emit('interactShow',selectValue.chart,selectValue.act)
            }
          }
        }
        
      }
    },
    // 建立连接、发起ws请求，以心跳方式，向服务端发送数据
    controlCreateWs() {
      this.controlWsObj = new WebSocket(process.env.VUE_APP_WEBSOCKET);
      // 若为对象类型，以回调方式发送
      websocketCommand(
        this.controlWsObj,
        "create",
        5000,
        this.chartOption.controlKey,
        this.controlSendHeartBeat,
        this.controlReceiveMsg,
        this.controlReconnectWs,
        this.controlWsWarning
      );
    },
    // 断网重连，需要处理的逻辑
    controlReconnectWs() {
      if (this.controlWsObj) {
        console.log("%c websocket_reconnect", "color:blue");
        this.controlCreateWs();
      }
    },
    // 以回调方式向服务端发送(对象类型的)心跳
    controlSendHeartBeat() {
      if (this.controlWsTimer != "") {
        clearTimeout(this.controlWsTimer);
      }

      let controlWsTimerTask = () => {
        console.log("发送心跳", "ping");
        let obj = { action: "keep", key: this.chartOption.controlKey };
        this.controlWsObj.send(JSON.stringify(obj));
        this.controlWsTimer = setTimeout(() => {
          controlWsTimerTask();
        }, parseInt(process.env.VUE_APP_WEBSOCKET_TIMEOUT));
        this.controlWsWarning();
      };
      controlWsTimerTask();
    },

    controlWsWarning() {
      //如果断开连接则显示组件警告动画并清除计数器
      if (this.controlWsObj.readyState == 3) {
        this.animate = "warning";
        clearTimeout(this.controlWsTimer);
      }
    },
    controlCloseWs() {
      clearTimeout(this.controlWsTimer);
      websocketCommand(
        this.controlWsObj,
        "close",
        5000,
        this.chartOption.controlKey,
        this.controlSendHeartBeat,
        this.controlReceiveMsg,
        this.controlReconnectWs,
        this.controlWsWarning
      );
      this.controlWsObj = null;
    },
    //  ws连接成功，后台返回的ws数据
    receiveMsg(e) {
      if (e.action == "chat") {
        // console.log('服务端推送',e);
        this.wsValue = e.result;
        this.setOptions(JSON.parse(JSON.stringify(this.chartOption)));
      }
    },
    // 建立连接、发起ws请求，以心跳方式，向服务端发送数据
    createWs() {
      this.wsObj = new WebSocket(process.env.VUE_APP_WEBSOCKET);
      // 若为对象类型，以回调方式发送
      websocketCommand(
        this.wsObj,
        "create",
        5000,
        this.chartOption.interfaceKey,
        this.sendHeartBeat,
        this.receiveMsg,
        this.reconnectWs,
        this.wsWarning
      );
    },
    // 断网重连，需要处理的逻辑
    reconnectWs() {
      if (this.wsObj) {
        console.log("%c websocket_reconnect", "color:blue");
        this.createWs();
      }
    },
    // 以回调方式向服务端发送(对象类型的)心跳
    sendHeartBeat() {
      if (this.wsTimer != "") {
        clearTimeout(this.wsTimer);
      }

      let wsTimerTask = () => {
        console.log("发送心跳", "ping");
        let obj = { action: "keep", key: this.chartOption.interfaceKey };
        this.wsObj.send(JSON.stringify(obj));
        this.wsTimer = setTimeout(() => {
          wsTimerTask();
        }, parseInt(process.env.VUE_APP_WEBSOCKET_TIMEOUT));
        this.wsWarning();
      };

      wsTimerTask();
    },
    wsWarning() {
      //如果断开连接则显示组件警告动画并清除计数器
      if (this.wsObj.readyState == 3) {
        this.animate = "warning";
        clearTimeout(this.wsTimer);
      }
    },
    closeWs() {
      clearTimeout(this.wsTimer);
      websocketCommand(
        this.wsObj,
        "close",
        5000,
        this.chartOption.interfaceKey,
        this.sendHeartBeat,
        this.receiveMsg,
        this.reconnectWs,
        this.wsWarning
      );
      this.wsObj = null;
    },    
    
  },
};
</script>

<style lang="scss" scoped>

</style>
